#include <iostream>
#include <vector>
#include <thread>
#include <chrono>
#include <memory>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/async.h"

// 测试函数：多线程日志写入性能
void spdlog_bench(const std::string &logger_name, size_t trd_cnt, size_t msg_cnt, size_t msg_len) {
    auto logger = spdlog::get(logger_name);
    if (!logger) {
        std::cerr << "获取日志器失败: " << logger_name << std::endl;
        return;
    }

    std::cout << "测试开始" << std::endl;
    std::vector<std::thread> threads;
    std::vector<double> trds_time(trd_cnt);
    std::string tmp(msg_len, 'a');  // 生成指定长度的测试字符串
    size_t msg_cnt_per_trd = msg_cnt / trd_cnt;
    size_t msg_size_per_trd = (msg_cnt_per_trd * msg_len) / 1024;  // 每条线程的总日志大小(kb)

    for (size_t i = 0; i < trd_cnt; ++i) {
        threads.emplace_back([&, i]() {
            auto start = std::chrono::high_resolution_clock::now();
            
            // 每条线程写入指定数量的日志
            for (size_t j = 0; j < msg_cnt_per_trd; ++j) {
                logger->critical("{}", tmp);  // 使用critical级别，对应原测试中的fatal
            }
            
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> time_gap = end - start;
            trds_time[i] = time_gap.count();

            // 输出单线程统计信息
            std::cout << "线程[" << i << "]" 
                      << "输出日志数：" << msg_cnt_per_trd << "条, "
                      << "总大小：" << msg_size_per_trd << "kb, "
                      << "总耗时：" << time_gap.count() << "s\n";
            std::cout << "\t每秒输出日志数：" << (size_t)(msg_cnt_per_trd / time_gap.count()) << "条\n";
            std::cout << "\t每秒输出日志大小：" << (size_t)(msg_size_per_trd / time_gap.count()) << "kb\n";
        });
    }

    // 等待所有线程完成
    for (auto &trd : threads) {
        trd.join();
    }

    // 计算总统计信息
    double max_cost = 0;
    for (double t : trds_time) {
        if (t > max_cost) {
            max_cost = t;
        }
    }

    std::cout << "总耗时: " << max_cost << "s" << std::endl;
    std::cout << "平均每秒输出日志数：" << (size_t)(msg_cnt / max_cost) << "条" << std::endl;
    std::cout << "平均每秒日志输出大小：" << (size_t)((msg_cnt * msg_len) / (max_cost * 1024)) << "kb" << std::endl;
}

// 同步日志测试
void spdlog_sync_bench(size_t trd_cnt, size_t msg_cnt, size_t msg_len) {
    // 创建同步文件日志器
    auto logger = spdlog::basic_logger_mt("spd_sync_logger", "./log/spd_synclogger.txt");
    logger->set_level(spdlog::level::critical);  // 设置为critical级别，只输出critical及以上
    // logger->set_pattern("%v");  // 仅输出日志内容，减少格式化开销（与原测试保持一致）
    
    spdlog_bench("spd_sync_logger", trd_cnt, msg_cnt, msg_len);
    
    // 清理日志器
    spdlog::drop("spd_sync_logger");
}

// 异步日志测试
void spdlog_async_bench(size_t trd_cnt, size_t msg_cnt, size_t msg_len,size_t async_trd_cnt) {
    // 初始化异步日志线程池
    spdlog::init_thread_pool(1024 * 1024, async_trd_cnt);  // 队列大小，后台线程
    
    // 创建异步文件日志器
    auto logger = spdlog::basic_logger_mt<spdlog::async_factory>("spd_async_logger", "./log/spd_asynclogger.txt");
    logger->set_level(spdlog::level::critical);  // 设置为critical级别
    // logger->set_pattern("%v");  // 仅输出日志内容
    
    spdlog_bench("spd_async_logger", trd_cnt, msg_cnt, msg_len);
    
    // 清理日志器
    spdlog::drop("spd_async_logger");
    spdlog::shutdown();  // 关闭异步线程池
}

int main() {
    std::cout<<"性能测试>>>>>"<<std::endl;
    std::cout << "同步单线程百万条日志：\n";
    spdlog_sync_bench(1, 1000000, 100);
    std::cout << "同步5线程百万条日志：\n";
    spdlog_sync_bench(5, 1000000, 100);
    std::cout << "同步10线程百万条日志：\n";
    spdlog_sync_bench(10, 1000000, 100);
    std::cout << "#####################################\n";
    std::cout << "异步单生产单消费线程百万条日志：\n";
    spdlog_async_bench(1, 1000000, 100,1);
    std::cout << "异步5生产单消费线程百万条日志：\n";
    spdlog_async_bench(5, 1000000, 100,1);
    std::cout << "异步10生产单消费线程百万条日志：\n";
    spdlog_async_bench(10, 1000000, 100,1);
    std::cout << "#####################################\n";
    std::cout << "异步单生产2消费线程百万条日志：\n";
    spdlog_async_bench(1, 1000000, 100,5);
    std::cout << "异步5生产2消费线程百万条日志：\n";
    spdlog_async_bench(5, 1000000, 100,5);
    std::cout << "异步10生产2消费线程百万条日志：\n";
    spdlog_async_bench(10, 1000000, 100,5);
    std::cout << "#####################################\n";
    std::cout << "异步单生产5消费线程百万条日志：\n";
    spdlog_async_bench(1, 1000000, 100,5);
    std::cout << "异步5生产5消费线程百万条日志：\n";
    spdlog_async_bench(5, 1000000, 100,5);
    std::cout << "异步10生产5消费线程百万条日志：\n";
    spdlog_async_bench(10, 1000000, 100,5);
    
    return 0;
}